/****************************************************************************
* copyright            : (C) 2009 William Viana Soares <vianasw@gmail.com>  *
*****************************************************************************/

/****************************************************************************
*                                                                           *
*   This program is free software; you can redistribute it and/or modify    *
*   it under the terms of the GNU General Public License as published by    *
*   the Free Software Foundation; either version 2 of the License, or       *
*   (at your option) any later version.                                     *
*                                                                           *
*****************************************************************************/

#ifndef POINT_H
#define POINT_H

#include <iostream>
#include <map>
#include <set>
#include <string>
#include <boost/functional/hash.hpp>

namespace ConciseQSR
{
using namespace std;

class Reference;
typedef string BaseRelation;

/**
* @class Point
* @short A class that holds information about a point and its relations to a set of reference systems
*/ 
class Point{
public:
    //probar con reales
    Point( string label = "", int x = 0, int y = 0 ): m_label( label ), m_x( x ), m_y( y ) {};
    ~Point(){};
    
    void addRelation( BaseRelation rel, Reference refsys );
    bool hasRelationWith( const Reference &refsys ) const { return m_relations.find( refsys ) != m_relations.end(); };
    const map< Reference, set< BaseRelation > >& getRelations() const{ return m_relations; };
    void showRelations() const;
    
    bool operator==( const Point &o ) const{ return m_label == o.m_label; };
    friend ostream& operator<<( ostream &os, const Point &p );
            
    int x() const { return m_x; };
    int y() const { return m_y; };
    const string& label() const{ return m_label; };
    string str() const;
    
        
private:
    string   m_label;
    int      m_x;
    int      m_y;
    map< Reference, set< BaseRelation > > m_relations; 

};

/**
* @class Reference
* @short A class that holds information about a reference system
*/
class Reference
{
public:
    /**
    * @param a one of the points of the reference system
    * @param b one of the points of the reference system
    * @param isOpen indicates if the reference system is physicaly connected in which case its value is false
    */
    Reference( Point a = Point(), Point b = Point(), bool isOpen = false );
    
    /**
    * @param o another reference system
    * @return true if both reference systems have the same orientation
    */
    bool sameOrientation( const Reference &o ) const{ return m_pointA == o.m_pointA && m_pointB == o.m_pointB; };
    
    Point first() const{ return m_pointA; };
    Point second() const{ return m_pointB; };
    friend ostream& operator<<( ostream &os, const Reference &r );
    bool operator==( const Reference &o ) const;        
    bool operator<( const Reference &o ) const;
    bool isOpen() const { return m_isOpen; };
    string str() const;
private:
    Point m_pointA;
    Point m_pointB;
    bool  m_isOpen;
    set< string > m_points; //internal representation used for comparisons.
    
};
} //namespace ConciseQSR
#endif